package com.atguigu.lease.web.admin.service.impl;

import com.atguigu.lease.model.entity.*;
import com.atguigu.lease.model.enums.ItemType;
import com.atguigu.lease.web.admin.mapper.*;
import com.atguigu.lease.web.admin.service.*;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentSubmitVo;
import com.atguigu.lease.web.admin.vo.graph.GraphVo;
import com.atguigu.lease.web.admin.vo.room.RoomDetailVo;
import com.atguigu.lease.web.admin.vo.room.RoomItemVo;
import com.atguigu.lease.web.admin.vo.room.RoomQueryVo;
import com.atguigu.lease.web.admin.vo.room.RoomSubmitVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * @author liubo
 * @description 针对表【room_info(房间信息表)】的数据库操作Service实现
 * @createDate 2023-07-24 15:48:00
 */
@Service
public class RoomInfoServiceImpl extends ServiceImpl<RoomInfoMapper, RoomInfo> implements RoomInfoService {

    @Autowired
    private RoomInfoMapper roomInfoMapper;

    @Autowired
    private ApartmentInfoMapper apartmentInfoMapper;

    @Autowired
    private ProvinceInfoService provinceInfoService;

    @Autowired
    private CityInfoService cityInfoService;

    @Autowired
    private DistrictInfoService districtInfoService;

    @Autowired
    private GraphInfoMapper graphInfoMapper;

    @Autowired
    private AttrValueMapper attrValueMapper;

    @Autowired
    private FacilityInfoMapper facilityInfoMapper;

    @Autowired
    private LabelInfoMapper labelInfoMapper;

    @Autowired
    private PaymentTypeMapper paymentTypeMapper;

    @Autowired
    private LeaseTermMapper leaseTermMapper;

    @Autowired
    private GraphInfoService graphInfoService;

    @Autowired
    private RoomAttrValueService roomAttrValueService;

    @Autowired
    private RoomFacilityService roomFacilityService;

    @Autowired
    private RoomLabelService roomLabelService;

    @Autowired
    private RoomPaymentTypeService roomPaymentTypeService;

    @Autowired
    private RoomLeaseTermService roomLeaseTermService;

    @Override
    public IPage<RoomItemVo> pageRoomItemByQuery(Page<RoomItemVo> roomItemVoPage, RoomQueryVo queryVo) {
        return roomInfoMapper.pageRoomItemByQuery(roomItemVoPage,queryVo);
    }

    @Override
    public RoomDetailVo getRoomById(Long id) {
        RoomInfo roomInfo = roomInfoMapper.selectById(id);

        if(roomInfo == null)
            return null;

        RoomDetailVo roomDetailVo = new RoomDetailVo();

        roomDetailVo.setApartmentInfo(apartmentInfoMapper.selectById(roomInfo.getApartmentId()));

        BeanUtils.copyProperties(roomInfo,roomDetailVo);

        roomDetailVo.setGraphVoList(graphInfoMapper.getGraphVoListByItemId(id, ItemType.ROOM));

        roomDetailVo.setAttrValueVoList(attrValueMapper.selectAttrValueVoListByRoomId(id));

        roomDetailVo.setFacilityInfoList(facilityInfoMapper.selectFacilityInfoListByRoomId(id));

        roomDetailVo.setLabelInfoList(labelInfoMapper.selectLabelInfoListByRoomId(id));

        roomDetailVo.setPaymentTypeList(paymentTypeMapper.selectPaymentTypeListByRoomId(id));

        roomDetailVo.setLeaseTermList(leaseTermMapper.selectLeaseTermListByRoomId(id));

        return roomDetailVo;
    }

    @Override
    public void saveOrUpdateRoom(RoomSubmitVo roomSubmitVo) {
        boolean isUpdate = roomSubmitVo.getId() == null ? false : true;
        if(isUpdate){
            delectRoomTagList(roomSubmitVo);
        }

        List<GraphVo> graphVoList = roomSubmitVo.getGraphVoList();
        if(graphVoList.size() > 0){
            List<GraphInfo> graphInfoList = new ArrayList<>();
            for (GraphVo graphVo : graphVoList) {
                GraphInfo graphInfo = new GraphInfo();
                graphInfo.setName(graphVo.getName());
                graphInfo.setItemType(ItemType.ROOM);
                graphInfo.setItemId(roomSubmitVo.getId());
                graphInfo.setUrl(graphVo.getUrl());
                graphInfoList.add(graphInfo);
            }
            graphInfoService.saveBatch(graphInfoList);
        }

        try {
            reflectUpdateMethod(roomSubmitVo.getAttrValueIds(), RoomAttrValue.class, roomSubmitVo,roomAttrValueService);

            reflectUpdateMethod(roomSubmitVo.getFacilityInfoIds(),RoomFacility.class,roomSubmitVo,roomFacilityService);

            reflectUpdateMethod(roomSubmitVo.getLabelInfoIds(),RoomLabel.class,roomSubmitVo,roomLabelService);

            reflectUpdateMethod(roomSubmitVo.getPaymentTypeIds(),RoomPaymentType.class,roomSubmitVo,roomPaymentTypeService);

            reflectUpdateMethod(roomSubmitVo.getLeaseTermIds(),RoomLeaseTerm.class,roomSubmitVo,roomLeaseTermService);
        }catch (Exception e){
            e.printStackTrace();
        }

        this.saveOrUpdate(roomSubmitVo);
    }

    @Override
    public void removeRoom(Long id) {
        this.removeById(id);

        RoomSubmitVo roomSubmitVo = new RoomSubmitVo();

        roomSubmitVo.setId(id);

        this.delectRoomTagList(roomSubmitVo);
    }

    public void delectRoomTagList(RoomSubmitVo roomSubmitVo){
        graphInfoService.remove(new LambdaQueryWrapper<GraphInfo>()
                .eq(GraphInfo::getItemType,ItemType.ROOM)
                .eq(GraphInfo::getItemId,roomSubmitVo.getId()));

        roomAttrValueService.remove(new LambdaQueryWrapper<RoomAttrValue>()
                .eq(RoomAttrValue::getRoomId,roomSubmitVo.getId()));

        roomFacilityService.remove(new LambdaQueryWrapper<RoomFacility>()
                .eq(RoomFacility::getRoomId,roomSubmitVo.getId()));

        roomLabelService.remove(new LambdaQueryWrapper<RoomLabel>()
                .eq(RoomLabel::getRoomId,roomSubmitVo.getId())
        );

        roomPaymentTypeService.remove(new LambdaQueryWrapper<RoomPaymentType>()
                .eq(RoomPaymentType::getRoomId,roomSubmitVo.getId()));

        roomLeaseTermService.remove(new LambdaQueryWrapper<RoomLeaseTerm>()
                .eq(RoomLeaseTerm::getRoomId,roomSubmitVo.getId()));
    }

    //通过反射剥离出添加或修改的重复操作
    public <T,U extends IService> void reflectUpdateMethod(List<Long> list, Class<T> clazz, RoomSubmitVo roomSubmitVo, U u) throws Exception {
        if(list.size() > 0){
            List<T> tList = new ArrayList<>();
            for (Long l : list) {
                Field[] declaredField = clazz.getDeclaredFields();
                T t = clazz.newInstance();
                for (Field field : declaredField) {
                    field.setAccessible(true);
                    String fieldName = field.getName();
                    if(fieldName.equals("roomId")){
                        field.set(t,roomSubmitVo.getId());
                    } else if (fieldName.equals("serialVersionUID")) {
                        continue;
                    } else {
                        field.set(t,l);
                    }
                }
                tList.add(t);
            }
            u.saveBatch(tList);
        }
    }
}




